package com.zwjstudy.cachestudy.redis7.lua.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * ClassName: LuaController
 * Package: com.zwjstudy.cachestudy.redis7.lua.controller
 * Description:
 *
 * @Author: 张文俊
 * @Create: 2025-09-23 - 9:19
 * @Version: v1.0
 */
@RestController
public class LuaController {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private int redisPort;
    @Value("${spring.redis.password}")
    private String redisPwd;


    // 定义计数器脚本对象
    private static final DefaultRedisScript<Long> COUNTER_SCRIPT;
    private static final DefaultRedisScript<Long> DEDUCT_STOCK_SCRIPT;

    static {
        COUNTER_SCRIPT = new DefaultRedisScript<>();
        COUNTER_SCRIPT.setLocation(new ClassPathResource("lua/counter.lua")); // 脚本文件放在 resources/lua/ 目录下
        COUNTER_SCRIPT.setResultType(Long.class); // 设置脚本返回类型

        DEDUCT_STOCK_SCRIPT = new DefaultRedisScript<>();
        DEDUCT_STOCK_SCRIPT.setLocation(new ClassPathResource("lua/deduct_stock.lua"));
        DEDUCT_STOCK_SCRIPT.setResultType(Long.class);
    }


    @GetMapping("/lua1")
    public String lua1(){

        Jedis jedis = new Jedis(redisHost, redisPort);
        jedis.auth(redisPwd);

        String luaScript = "local key = KEYS[1] " +
                "local current = redis.call('GET', key) " +
                "if current == false then " +
                "    redis.call('SET', key, 1) " +
                "    return 1 " +
                "else " +
                "    redis.call('INCR', key) " +
                "    return tonumber(current) + 1 " +
                "end";

        // 执行脚本，1表示KEYS数组的数量，后面是key和参数
        Object result = jedis.eval(luaScript, 1, "myCounter");
        System.out.println("Result: " + result);

        jedis.close();

        return String.valueOf(result);
    }

    @GetMapping("/lua2")
    public String lua2(){

        JedisPoolConfig config = new JedisPoolConfig();
        //最大连接数
        config.setMaxTotal(30);
        //最大连接空闲数
        config.setMaxIdle(2);

//        JedisPool pool = new JedisPool(config, this.redisHost, this.redisPort);
        //有密码也可以用下面这个连接方法
        JedisPool pool = new JedisPool(config,this.redisHost, this.redisPort ,3000, this.redisPwd);
        Jedis jedis = null;
        Object result = null;
        try  {
            jedis = pool.getResource();
            jedis.auth(this.redisPwd);
//            jedis.set("name", "123");
//            String name = jedis.get("name");
//            System.out.println(name);

            String luaScript = "local key = KEYS[1] " +
                    "local current = redis.call('GET', key) " +
                    "if current == false then " +
                    "    redis.call('SET', key, 1) " +
                    "    return 1 " +
                    "else " +
                    "    redis.call('INCR', key) " +
                    "    return tonumber(current) + 1 " +
                    "end";

            // 执行脚本，1表示KEYS数组的数量，后面是key和参数
            result = jedis.eval(luaScript, 1, "myCounter");
            System.out.println("Result: " + result);

        }catch(Exception ex){
            ex.printStackTrace();
        }finally{
            if(jedis != null){
                //关闭连接
                jedis.close();
            }
        }
        return String.valueOf(result);
    }

    @GetMapping("/lua3")
    public String lua3(){

        // 执行脚本。keys和args列表需与Lua脚本中的KEYS和ARGV对应
        Object result=redisTemplate.execute(COUNTER_SCRIPT, Arrays.asList("myCounter"));
        return String.valueOf(result);

    }

    @GetMapping("/lua4")
    public Long deductStock(String productId, Integer quantity) {
        String stockKey = "stock:" + productId;
        System.out.println("stockKey = " + stockKey);
        System.out.println("quantity = " + quantity);

        List<String> keys = Collections.singletonList(stockKey);
        List<String> values = Collections.singletonList(quantity.toString());

        return redisTemplate.execute(
                DEDUCT_STOCK_SCRIPT,
                keys,
                values
        );
    }

}
